#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "bigiot.h"
#include "bigiot.cfg"

#include "cJSON.h"

char *str_checkin = NULL;
char *str_beat = NULL;
char *str_update = NULL;
char *str_say = NULL;
char *str_status = NULL;
char *str_time = NULL;
char *str_checkout = NULL;
char *str_isOL = NULL;
char *str_alert = NULL;

void fun_checkin(void);
void fun_beat(void);
void fun_update(unsigned char);
void fun_say(char *);
void fun_status(void);
void fun_time(void);
void fun_checkout(void);
void fun_isOL(void);
void fun_alert(void);

int tcp_socket_bigiot;
struct sockaddr_in sockaddr_in_bigiot;

int ret;
char buf[1024];

void bigiot_connect(void);
void bigiot_checkin(void);
void bigiot_status(void);
void bigiot_time(void);
void bigiot_checkout(void);
void bigiot_isOL(void);
void bigiot_alert(void);

int init_bigiot(void *arg)
{
    fun_checkin();
    fun_beat();
    fun_status();
    fun_time();
    fun_checkout();
    fun_isOL();
    fun_alert();

    tcp_socket_bigiot = socket(AF_INET, SOCK_STREAM, 0);

    printf("socket:%d\n", tcp_socket_bigiot);

    if (tcp_socket_bigiot < 0)
    {
        printf("socket error!\n");
    }

    sockaddr_in_bigiot.sin_family = AF_INET;
    sockaddr_in_bigiot.sin_port = htons(PORT);

#if 1
    struct hostent *h;
    h = gethostbyname(DOMAIN);
    if (NULL == h)
    {
        herror("gethostbyname");
    }

    char *ip = inet_ntoa(*((struct in_addr *)h->h_addr_list[0]));
    sockaddr_in_bigiot.sin_addr.s_addr = inet_addr(ip);
#else
    sockaddr_in_bigiot.sin_addr.s_addr = inet_addr(IP);
#endif

    bigiot_connect();
#if 0
    bigiot_checkout();
#endif
    bigiot_checkin();

    bigiot_status();

    bigiot_time();

    bigiot_isOL();
#if 0
    bigiot_alert();
#endif
    return 0;
}

int period_handler_cmd(void *arg)
{
    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);

    /**
     * reconnect
     */
    if (0 == ret)
    {
        ret = init_bigiot(NULL);

        if (0 == ret)
        {
            printf("reconnect\n");
        }
    }

    return 0;
}

int period_handler_beat(void *arg)
{
    ret = send(tcp_socket_bigiot, str_beat, strlen(str_beat), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_beat);

    return 0;
}

int period_handler_update(void *arg)
{
    static unsigned char temp = 31;

    fun_update(temp);

    temp ++;

    ret = send(tcp_socket_bigiot, str_update, strlen(str_update), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_update);

    return 0;
}

void bigiot_connect(void)
{
    int ret;

    ret = connect(tcp_socket_bigiot, (const struct sockaddr *)&sockaddr_in_bigiot, sizeof(sockaddr_in_bigiot));

    printf("connect:%d\n", ret);

    if (ret < 0)
    {
        perror("connect");
    }

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void bigiot_checkin(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_checkin, strlen(str_checkin), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_checkin);

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void bigiot_checkout(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_checkout, strlen(str_checkout), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_checkout);

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void bigiot_isOL(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_isOL, strlen(str_isOL), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_isOL);

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void bigiot_alert(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_alert, strlen(str_alert), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_alert);
}

void bigiot_status(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_status, strlen(str_status), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_status);

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void bigiot_time(void)
{
    int ret;

    ret = send(tcp_socket_bigiot, str_time, strlen(str_time), 0);

    printf("send:%d\n", ret);

    if (ret < 0) {
        perror("send");
    }

    printf("%s", str_time);

    memset(buf, 0, sizeof(buf));
    ret = recv(tcp_socket_bigiot, buf, sizeof(buf), 0);

    printf("recv:%d\n", ret);

    if (ret < 0)
    {
        perror("recv");
    }

    printf("%s", buf);
}

void fun_checkin(void)
{
    cJSON *checkin = NULL;

    checkin = cJSON_CreateObject();

    if (NULL == checkin)
    {
        printf("cJSON error!\n");
    }

	cJSON_AddStringToObject(checkin, "M", "checkin");
	cJSON_AddStringToObject(checkin, "ID", ID);
	cJSON_AddStringToObject(checkin, "K", APIKEY);

    str_checkin = cJSON_PrintUnformatted(checkin);

    if (NULL == str_checkin)
    {
        printf("cJSON error!\n");
    }

	strcat(str_checkin, "\n");

    printf("%s", str_checkin);
}

void fun_beat(void)
{
    cJSON *beat = NULL;

	beat = cJSON_CreateObject();

	if (NULL == beat)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(beat, "M", "beat");

	str_beat = cJSON_PrintUnformatted(beat);

	if (NULL == str_beat)
    {
		printf("cJSON error!\n");
	}

	strcat(str_beat, "\n");
}

void fun_update(unsigned char temp)
{
    char str_buf[1024];

    cJSON *data = NULL;

    data = cJSON_CreateObject();

    if (NULL == data)
    {
        printf("cJSON error!\n");
    }

    sprintf(str_buf, "%d", temp);

    cJSON_AddStringToObject(data, DID, str_buf);

    cJSON *update = NULL;

    update = cJSON_CreateObject();

    if (NULL == update)
    {
        printf("cJSON error!\n");
    }

    cJSON_AddStringToObject(update, "M", "update");
    cJSON_AddStringToObject(update, "ID", ID);
    cJSON_AddItemToObject(update, "V", data);

    str_update = cJSON_PrintUnformatted(update);

    if (NULL == str_update)
    {
        printf("cJSON error!\n");
    }

    strcat(str_update, "\n");
}

void fun_say(char *cmd)
{
    cJSON *say = NULL;

    say = cJSON_CreateObject();

    if (NULL == say)
    {
        printf("cJSON error!\n");
    }

    cJSON_AddStringToObject(say, "M", "say");
    cJSON_AddStringToObject(say, "ID", UID);
    cJSON_AddStringToObject(say, "C", cmd);

    str_say = cJSON_PrintUnformatted(say);

    if (NULL == str_say)
    {
        printf("cJSON error!\n");
    }

    strcat(str_say, "\n");
}

void fun_status(void)
{
    cJSON *status = NULL;

	status = cJSON_CreateObject();

	if (NULL == status)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(status, "M", "status");

	str_status = cJSON_PrintUnformatted(status);

	if (NULL == str_status)
    {
		printf("cJSON error!\n");
	}

	strcat(str_status, "\n");
}

void fun_time(void)
{
    cJSON *time = NULL;

	time = cJSON_CreateObject();

	if (NULL == time)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(time, "M", "time");
    cJSON_AddStringToObject(time, "F", "Y-m-d H:i:s");

	str_time = cJSON_PrintUnformatted(time);

	if (NULL == str_time)
    {
		printf("cJSON error!\n");
	}

	strcat(str_time, "\n");
}

void fun_checkout(void)
{
    cJSON *checkout = NULL;

	checkout = cJSON_CreateObject();

	if (NULL == checkout)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(checkout, "M", "checkout");
    cJSON_AddStringToObject(checkout, "ID", ID);
    cJSON_AddStringToObject(checkout, "K", APIKEY);

	str_checkout = cJSON_PrintUnformatted(checkout);

	if (NULL == str_checkout)
    {
		printf("cJSON error!\n");
	}

	strcat(str_checkout, "\n");
}

void fun_isOL(void)
{
    cJSON *isOL = NULL;

	isOL = cJSON_CreateObject();

	if (NULL == isOL)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(isOL, "M", "isOL");
    cJSON_AddStringToObject(isOL, "ID", ID);

	str_isOL = cJSON_PrintUnformatted(isOL);

	if (NULL == str_isOL)
    {
		printf("cJSON error!\n");
	}

	strcat(str_isOL, "\n");
}

void fun_alert(void)
{
    cJSON *alert = NULL;

	alert = cJSON_CreateObject();

	if (NULL == alert)
    {
		printf("cJSON error!\n");
	}

	cJSON_AddStringToObject(alert, "M", "alert");
    cJSON_AddStringToObject(alert, "ID", AID);
    cJSON_AddStringToObject(alert, "C", "test");

	str_alert = cJSON_PrintUnformatted(alert);

	if (NULL == str_alert)
    {
		printf("cJSON error!\n");
	}

	strcat(str_alert, "\n");
}
